home *** CD-ROM | disk | FTP | other *** search
/ PC Advisor 2010 April / PCA177.iso / ESSENTIALS / Firefox Setup.exe / nonlocalized / components / NetworkGeolocationProvider.js < prev    next >
Encoding:
Text File  |  2009-07-15  |  9.3 KB  |  280 lines

  1. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  2.  
  3. const Ci = Components.interfaces;
  4. const Cc = Components.classes;
  5.  
  6. function nowInSeconds()
  7. {
  8.     return Date.now() / 1000;
  9. }
  10.  
  11. function LOG(aMsg) {
  12.     //aMsg = ("*** WIFI GEO: " + aMsg);
  13.     //Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(aMsg);
  14. }
  15.  
  16. function getAccessTokenForURL(url)
  17. {
  18.     // check to see if we have an access token:
  19.     var accessToken = "";
  20.     
  21.     try {
  22.         var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  23.  
  24.         var accessTokenPrefName = "geo.wifi.access_token." + url;
  25.         accessToken = prefService.getCharPref(accessTokenPrefName);
  26.         
  27.         // check to see if it has expired
  28.         var accessTokenDate = prefService.getIntPref(accessTokenPrefName + ".time");
  29.         
  30.         var accessTokenInterval = 1209600;  /* seconds in 2 weeks */
  31.         try {
  32.             accessTokenInterval = prefService.getIntPref("geo.wifi.access_token.recycle_interval");
  33.         } catch (e) {}
  34.         
  35.         if (nowInSeconds() - accessTokenDate > accessTokenInterval)
  36.             accessToken = "";
  37.     }
  38.     catch (e) {
  39.         accessToken = "";
  40.         LOG("Error: "+ e);
  41.     }
  42.     return accessToken;
  43. }
  44.  
  45. function WifiGeoCoordsObject(lat, lon, acc) {
  46.     this.latitude = lat;
  47.     this.longitude = lon;
  48.     this.accuracy = acc;
  49. };
  50.  
  51. WifiGeoCoordsObject.prototype = {
  52.  
  53.     QueryInterface:   XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords, Ci.nsIClassInfo]),
  54.  
  55.     getInterfaces: function(countRef) {
  56.         var interfaces = [Ci.nsIDOMGeoPositionCoords, Ci.nsIClassInfo, Ci.nsISupports];
  57.         countRef.value = interfaces.length;
  58.         return interfaces;
  59.     },
  60.  
  61.     getHelperForLanguage: function(language) null,
  62.     contractID: "",
  63.     classDescription: "wifi geo position coords object",
  64.     classID: null,
  65.     implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
  66.     flags: Ci.nsIClassInfo.DOM_OBJECT,
  67.  
  68.     latitude: 0,
  69.     longitude: 0,
  70.     accuracy: 0,
  71.  
  72.     altitude: 0,
  73.     altitudeAccuracy: 0,
  74.     heading: 0,
  75.     speed: 0,
  76. };
  77.  
  78. function WifiGeoPositionObject(lat, lon, acc) {
  79.     this.coords = new WifiGeoCoordsObject(lat, lon, acc);
  80.     this.timestamp = Date.now();
  81. };
  82.  
  83. WifiGeoPositionObject.prototype = {
  84.  
  85.     QueryInterface:   XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition, Ci.nsIClassInfo]),
  86.  
  87.     // Class Info is required to be able to pass objects back into the DOM.
  88.     getInterfaces: function(countRef) {
  89.         var interfaces = [Ci.nsIDOMGeoPosition, Ci.nsIClassInfo, Ci.nsISupports];
  90.         countRef.value = interfaces.length;
  91.         return interfaces;
  92.     },
  93.  
  94.     getHelperForLanguage: function(language) null,
  95.     contractID: "",
  96.     classDescription: "wifi geo location position object",
  97.     classID: null,
  98.     implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
  99.     flags: Ci.nsIClassInfo.DOM_OBJECT,
  100.  
  101.     coords: null,
  102.     timestamp: 0,
  103. };
  104.  
  105. function WifiGeoPositionProvider() {};
  106. WifiGeoPositionProvider.prototype = {
  107.     classDescription: "A component that returns a geolocation based on WIFI",
  108.     classID:          Components.ID("{77DA64D3-7458-4920-9491-86CC9914F904}"),
  109.     contractID:       "@mozilla.org/geolocation/provider;1",
  110.     QueryInterface:   XPCOMUtils.generateQI([Ci.nsIGeolocationProvider, Ci.nsIWifiListener, Ci.nsITimerCallback]),
  111.   
  112.     provider_url:    null,
  113.     wifi_service:    null,
  114.     timer:           null,
  115.     hasSeenWiFi:     false,
  116.  
  117.     observe: function (aSubject, aTopic, aData) {
  118.         if (aTopic == "private-browsing") {
  119.             if (aData == "enter" || aData == "exit") {
  120.                 let psvc = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
  121.                 try {
  122.                     let branch = psvc.getBranch("geo.wifi.access_token.");
  123.                     branch.deleteBranch("");
  124.                 } catch (e) {}
  125.             }
  126.         }
  127.     },
  128.  
  129.     startup:         function() {
  130.         LOG("startup called");
  131.  
  132.         var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  133.         this.provider_url = prefService.getCharPref("geo.wifi.uri");
  134.         LOG("provider url = " + this.provider_url);
  135.  
  136.         // if we don't see anything in 5 seconds, kick of one IP geo lookup.
  137.         this.hasSeenWiFi = false;
  138.         this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
  139.         this.timer.initWithCallback(this, 5000, this.timer.TYPE_ONE_SHOT);
  140.  
  141.         let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
  142.         os.addObserver(this, "private-browsing", false);
  143.     },
  144.  
  145.     isReady:         function() {
  146.         LOG("isReady called");
  147.         return true
  148.     },
  149.   
  150.     watch: function(c) {
  151.         LOG("watch called");
  152.         if (!this.wifi_service) {
  153.             this.wifi_service = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
  154.             this.wifi_service.startWatching(this);
  155.         }
  156.     },
  157.  
  158.     shutdown: function() { 
  159.         LOG("shutdown  called");
  160.         if(this.wifi_service)
  161.             this.wifi_service.stopWatching(this);
  162.         this.wifi_service = null;
  163.  
  164.         if (this.timer != null) {
  165.             this.timer.cancel();
  166.             this.timer = null;
  167.         }
  168.  
  169.         // Although we aren't using cookies, we should err on the side of not
  170.         // saving any access tokens if the user asked us not to save cookies or
  171.         // has changed the lifetimePolicy.  The access token in these cases is
  172.         // used and valid for the life of this object (eg. between startup and
  173.         // shutdown).e
  174.         let prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  175.         if (prefBranch.getIntPref("network.cookie.lifetimePolicy") != 0)
  176.             prefBranch.deleteBranch("geo.wifi.access_token.");
  177.  
  178.         let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
  179.         os.removeObserver(this, "private-browsing");
  180.     },
  181.  
  182.     onChange: function(accessPoints) {
  183.  
  184.         LOG("onChange called");
  185.         this.hasSeenWiFi = true;
  186.  
  187.         var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  188.  
  189.         // send our request to a wifi geolocation network provider:
  190.         var xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
  191.  
  192.         // This is a background load
  193.         xhr.mozBackgroundRequest = true;
  194.  
  195.         xhr.open("POST", this.provider_url, false);
  196.         
  197.         // set something so that we can strip cookies
  198.         xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
  199.             
  200.         xhr.onerror = function(req) {
  201.             LOG("onerror: " + req);
  202.         };
  203.  
  204.         xhr.onload = function (req) {  
  205.  
  206.             LOG("service returned: " + req.target.responseText);
  207.  
  208.             // if we get a bad response, we will throw and never report a location
  209.             var response = JSON.parse(req.target.responseText);
  210.  
  211.             // response looks something like:
  212.             // {"location":{"latitude":51.5090332,"longitude":-0.1212726,"accuracy":150.0},"access_token":"2:jVhRZJ-j6PiRchH_:RGMrR0W1BiwdZs12"}
  213.  
  214.             // Check to see if we have a new access token
  215.             var newAccessToken = response.access_token;
  216.             if (newAccessToken != undefined)
  217.             {
  218.                 var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  219.                 var accessToken = "";
  220.                 var accessTokenPrefName = "geo.wifi.access_token." + req.target.channel.URI.spec;
  221.                 try { accessToken = prefService.getCharPref(accessTokenPrefName); } catch (e) {}
  222.  
  223.                 if (accessToken != newAccessToken) {
  224.                     // no match, lets cache
  225.                     LOG("New Access Token: " + newAccessToken + "\n" + accessTokenPrefName);
  226.                     
  227.                     prefService.setIntPref(accessTokenPrefName + ".time", nowInSeconds());
  228.                     prefService.setCharPref(accessTokenPrefName, newAccessToken);
  229.                 }
  230.             }
  231.  
  232.             var newLocation = new WifiGeoPositionObject(response.location.latitude,
  233.                                                         response.location.longitude,
  234.                                                         response.location.accuracy);
  235.  
  236.             var update = Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate);
  237.             update.update(newLocation);
  238.         };
  239.  
  240.         var accessToken = getAccessTokenForURL(this.provider_url);
  241.  
  242.         var request = {
  243.             version: "1.1.0",
  244. //          request_address: true,
  245.         };
  246.  
  247.         if (accessToken != "")
  248.             request.access_token = accessToken;
  249.  
  250.         if (accessPoints != null) {
  251.             request.wifi_towers = accessPoints.map(function (ap) ({
  252.                         mac_address: ap.mac,
  253.                         ssid: ap.ssid,
  254.                         signal_strength: ap.signal,
  255.                     }));
  256.         }
  257.  
  258.         var jsonString = JSON.stringify(request);
  259.         LOG("client sending: " + jsonString);
  260.  
  261.         xhr.send(jsonString);
  262.     },
  263.  
  264.     onError: function (code) {
  265.         LOG("wifi error: " + code);
  266.     },
  267.  
  268.     notify: function (timer) {
  269.         if (this.hasSeenWiFi == false)
  270.             this.onChange(null);
  271.         this.timer = null;
  272.     },
  273.  
  274. };
  275.  
  276. var components = [WifiGeoPositionProvider];
  277. function NSGetModule(compMgr, fileSpec) {
  278.   return XPCOMUtils.generateModule(components);
  279. }
  280.